package org.zerta.troops.xml;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.awt.Point;

import org.zerta.troops.common.Area;
import org.zerta.troops.common.World;

public class WorldUnmarshaler {
	
	World world;
	
	Map<String, List<String>> neighborMap;
	
	public World unmarshalWorld ( Node rootNode ) {
		world = new World();
		neighborMap = new HashMap<String, List<String>>();
		
		Node n;
		NodeList nodes = rootNode.getChildNodes();
		
		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				if (n.getNodeName().equals("Information")) {
					unmarshalInformation(n);
				} else if (n.getNodeName().equals("Areas")) {
					unmarshalAreas(n);
					for ( 	Iterator <String> neighborMapIterator = neighborMap.keySet().iterator();
							neighborMapIterator.hasNext(); 
							) {
						String areaName = neighborMapIterator.next();
						Area area = world.findArea(areaName);
						if (area != null) {
							for ( 	Iterator <String> neighborListIterator = neighborMap.get(areaName).iterator(); 
									neighborListIterator.hasNext() ;
									) {
								String neighborName = neighborListIterator.next();
								Area neighbor = world.findArea(neighborName);
								if (neighbor != null) {
									area.addNeighbor(neighbor);
								}
							}
						}
					}
				} else {
					// Unknown element node in World
				}
			} else {
				// Unknown node-type in World
			}
		}
		
		return world;
	}
	
	private void unmarshalInformation( Node informationNode ) {
		Node n;
		NodeList nodes = informationNode.getChildNodes();
		
		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				if (n.getNodeName().equals("Name")) {
					String name = unmarshalText(n);
					world.setName(name);
				} else {
					// Unknown element in PlayerData
				}
			} else {
				// Unknown node-type in PlayerData
			}
		}
	}

	private void unmarshalAreas( Node areasNode ) {
		Node n;
		NodeList nodes = areasNode.getChildNodes();
		
		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				if (n.getNodeName().equals("Area")) {
					Area area = unmarshalArea(n);
					world.addArea(area);
				} else {
					// Unknown element in Areas
				}
			} else {
				// Unknown node-type in Areas
			}
		}
	}
	
	private Area unmarshalArea ( Node areaNode ) {
		Area area = new Area();
		List <String> neighborsList = null;
		Node n;
		NodeList nodes = areaNode.getChildNodes();
		
		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				if (n.getNodeName().equals("Name")) {
					String name = unmarshalText(n);
					area.setName(name);
				} else if (n.getNodeName().equals("Position")) {
					Point position = unmarshalPosition(n);
					area.setPosition(position);
				} else if (n.getNodeName().equals("Neighbors")) {
					neighborsList = unmarshalNeighbors(n);
				} else {
					// Unknown element in Area
				}
			} else {
				// Unknown node-type in Area
			}
		}
		if (neighborsList != null && area.getName() != null) {
			neighborMap.put(area.getName(), neighborsList);			
		}
		return area;
	}
	
	private List<String> unmarshalNeighbors( Node neighborsNode ) {
		List <String> neighborsList = new LinkedList<String>();
		Node n;
		NodeList nodes = neighborsNode.getChildNodes();

		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				if (n.getNodeName().equals("Neighbor")) {
					String neighborName = unmarshalText(n);
					neighborsList.add(neighborName);
				} else {
					// Unknown element in Neighbors
				}
			} else {
				// Unknown node-type in Neighbors
			}
		}
		return neighborsList;
	}
	
	private Point unmarshalPosition( Node positionNode ) {
		Point position = new Point();
		Node n;
		NodeList nodes = positionNode.getChildNodes();

		Integer x = null;
		Integer y = null;
		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				if (n.getNodeName().equals("X")) {
					x = new Integer(unmarshalText(n));
				} else if (n.getNodeName().equals("Y")) {
					y = new Integer(unmarshalText(n));
				} else {
					// Unknown element in Position
				}
			} else {
				// Unknown node-type in Position
			}
		}
		
		if (x != null && y != null) {
			position.setLocation(x.intValue(), y.intValue());
		}
		return position;
	}
	
	private String unmarshalText ( Node textNode ) {
		StringBuffer buffer = new StringBuffer();
		
		Node n;
		NodeList nodes = textNode.getChildNodes();
		
		for (int i = 0; i < nodes.getLength(); i++) {
			n = nodes.item(i);
			if (n.getNodeType() == Node.TEXT_NODE) {
				buffer.append( n.getNodeValue() );
			} else {
				// Unknown node-type in unmarshalText
			}
		}
		return buffer.toString();
	}
	

	
}
